#!/usr/bin/env bash

#get this script real directory
SOURCE=$BASH_SOURCE
while [ -h "$SOURCE"  ]; do # resolve $SOURCE until the file is no longer a symlink
    this_script_dir_global_2021="$( cd -P "$( dirname "$SOURCE"  )" && pwd  )"
    SOURCE="$(readlink "$SOURCE")"
    # if $SOURCE was a relative symlink, 
    #we need to resolve it relative to the path 
    #where the symlink file was located
    [[ $SOURCE != /*  ]] && SOURCE="$this_script_dir_global_2021/$SOURCE"
done
this_script_dir_global_2021="$( cd -P "$( dirname "$SOURCE"  )" && pwd  )"
tty -s && mesg n || true
source $this_script_dir_global_2021/insert_profile.sh

_arg_num_=$#

if [ -f ~/.profile ] ; then
    source ~/.profile
fi

shopt -s expand_aliases

log_dir=~/git/run/log
log_file="$log_dir/shell_global.log"
if [ ! -d $log_dir ] ; then
    mkdir -p $log_dir
fi

#should_log_leve=error
#should_log_leve=error
log_level=${log_level:=warn}

log_level_to_int()
{
    local level="$1"
    local ret=0
    if   [ "$level" == trace    ] ; then  ret=1
    elif [ "$level" == debug    ] ; then  ret=2
    elif [ "$level" == info     ] ; then  ret=3
    elif [ "$level" == warn     ] ; then  ret=4
    elif [ "$level" == error    ] ; then  ret=5
    elif [ "$level" == critical ] ; then  ret=6
    #elif [ "$level" == ] ; then 
    fi
    return $ret
}

log_level_is_debug_mode()
{
    local user_log_level=$1

    log_level_to_int $user_log_level
    local user_log_level_int=$?

    log_level_to_int debug
    local debug_log_level_int=$?

    if [ $user_log_level_int -le $debug_log_level_int ] ; then
        return 0
    else
        return 1
    fi
}

should_log()
{
    local ret=1
    log_level_to_int $1
    local level_int=$?

    #log_level_to_int $should_log_leve
    log_level_to_int $log_level
    local user_set_log_leve_int=$?

    if [ $level_int -ge $user_set_log_leve_int ] ; then
        ret=0;
    fi

    return $ret
}

vlog()
{
    local log_file="$log_dir/shell_global.log"
    local level="$1"
    local file_name="$2"
    local line_num="$3"
    local func_name="$4"
    local fmt=""
    local log_to_screen=true
    should_log $level || log_to_screen=false

    #if()

    shift
    shift
    shift
    shift

    #printf "%s" "[`date +%Y-%m-%d_%H:%M:%S`] [$level] [${LINENO}L]"
    #printf "[%s] [\033[1;31m%s\033[0m] " "`date +%Y-%m-%d_%H:%M:%S`" "$level"

    #local log_str="[`date +"%Y-%m-%d %H:%M:%S"`] [$level] [`basename "$file_name"`:${line_num} $func_name] "
    #local log_str="[`date +"Y-%m-%d %H:%M:%S"`] [$level] [${file_name##*/}:${line_num} $func_name] "
    local log_str="[`date +"%m-%d %H:%M:%S"`] [$level] [${file_name##*/}:${line_num} $func_name] "
    while [ -n "$1" ]; do
        #support printf "%s %i %m.nf"
        echo "$1" | grep -E "%-?[0-9]*.?[0-9]*[sif]" > /dev/null
        if [ $? -eq 0 ]  ; then
            fmt="$1"
        else
            if [ -n "$fmt" ] ; then
                log_str="${log_str}`printf "${fmt}" "$@"`"
                fmt=""
                break
            else
                log_str="${log_str}$1"
            fi
        fi
        shift
    done

    #printf "%s\n" "$log_str" >&2 
    #printf "%s\n" "$log_str" | tee -a $log_file >&2

    #if [ -n "$show" ] ; then
    if [ "$log_to_screen" == true ] ; then
        if [ "$level" == "error" ] || [ "$level" == "critical" ] ; then
            #not only log into file also log into stderr (by >&2)
            printf "%s\n" "$log_str" | tee -a $log_file >&2
        else
            printf "%s\n" "$log_str" | tee -a $log_file
        fi
    else
        if [ "$level" == "error" ] || [ "$level" == "critical" ] ; then
            printf "%s\n" "$log_str" | tee -a $log_file >&2
        else
            printf "%s\n" "$log_str" >> $log_file
        fi
    fi
    return 0;
}

#vlogt(){ vlog trace    "$@" ; }
#vlogd(){ vlog debug    "$@" ; }
#vlogi(){ vlog info     "$@" ; }
#vlogw(){ vlog warn     "$@" ; }
#vloge(){ vlog error    "$@" ; }
#vlogc(){ vlog critical "$@" ; }

vlogt_(){ vlog trace    "$@" ; }
vlogd_(){ vlog debug    "$@" ; }
vlogi_(){ vlog info     "$@" ; }
vlogw_(){ vlog warn     "$@" ; }
vloge_(){ vlog error    "$@" ; }
vlogc_(){ vlog critical "$@" ; }

alias vlogt='vlogt_ $BASH_SOURCE $LINENO $FUNCNAME\(\)'
alias vlogd='vlogd_ $BASH_SOURCE $LINENO $FUNCNAME\(\)'
alias vlogi='vlogi_ $BASH_SOURCE $LINENO $FUNCNAME\(\)'
alias vlogw='vlogw_ $BASH_SOURCE $LINENO $FUNCNAME\(\)'
alias vloge='vloge_ $BASH_SOURCE $LINENO $FUNCNAME\(\)'
alias vlogc='vlogc_ $BASH_SOURCE $LINENO $FUNCNAME\(\)'

#alias vlogi='vlogi $LINENO'

parse_arguments() 
{
    local key="";
    local value="";
    local current="";
    cmd_log_to_screen=false

    while [ "$1" != "" ]; do
        #echo "01 arg:$1"
        current=$1;
        #echo "0 current arg:[$current]"
        if [ -z "${current##* }" ] ; then 
            shift
            continue; 
        fi
        key=${current##*--};
        #echo "1:$key"
        key=${key%%=*}
        #echo "2:$key"

        #key=$(echo "$key" | tr '-' '_');
        #key=${key//-/_};
        #echo "3:$key"
        value=${current#*=};
        #echo "a:$value"

        if [ "$value" == "$current" ]; then
            value=$key;
        fi

        #echo "b:$value"
        #echo "eval $key=\"$value\"";

        value=${value//$/\\$};
        #echo "c:$value"

        eval "$key=\"$value\"";
        #eval "arg_$key=\"$value\"";

        if [ "$key" == "log_level" ] ; then
            should_log debug && cmd_log_to_screen=true
        fi

        shift
    done
}


check_argument()
{
    local ret=0
    while [ -n "$1" ]; do
        #param: username , check whether init --username in argument
        local key="";
        local value="";
        arg="$1"
        eval "value=\${$arg}"

        if [ -z "$value" ]; then
            vloge "can not found argument \"--$arg=\", needed by $0"
            ret=1 
        fi
        shift
    done
    return $ret
}


#if has ip's format is wrong,return failed.
check_ip_valid()
{
    local ret=0

    while [ "$1" != "" ]; do
        local ip=$1
        local ip_null=$(echo "$ip" | sed "s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}//")
        #echo "after sed replace ip:$ip_null"
        if [ -n "$ip_null"  ] ; then
            ip_null=$(echo "$ip" | sed "s/\([0-9a-zA-Z_]\{1,128\}\.\)\{1,8\}[a-zA-Z]\{1,5\}//")
            #echo "after sed replace ip:$ip_null"
            if [ -n "$ip_null" ] ; then
                vloge "ip:\"$ip\" is not valid, please check ip's format"
                ret=1
            fi
        fi

        shift
    done

    return $ret
}

init()
{
   echo "jjjjjjjjjjj:$BASH_SOURCE"
}

parse_arguments "$@" #must have "" on $@ ,or result in wrong num of args in function




